//
//  UIView+LayoutMethods.swift
//  Signup
//
//  Created by heze on 2018/9/30.
//  Copyright © 2018 apple. All rights reserved.
//

import Foundation
import UIKit

extension HZLayoutable where L:UIView {
    
    //介词
    func end() {
        
    }
    
    var and: ExtensionHZLayoutable<UIView> {
        
        return ly.ly
    }
    
    //MARK: methods
    // imbueset
    func fill() -> ExtensionHZLayoutable<UIView>  {
        
        ly.frame = ly.superview?.bounds ?? CGRect()
        
        return ly.ly
    }
    func fillWidth() -> ExtensionHZLayoutable<UIView> {
        ly.frame.size.width = ly.superview?.ly.width ?? 0
        return ly.ly
    }
    func fullHeight() -> ExtensionHZLayoutable<UIView> {
        ly.frame.size.height = ly.superview?.ly.width ?? 0
        return ly.ly
    }
    
    func heightEqual(_ view: UIView) -> ExtensionHZLayoutable<UIView> {
        ly.frame.size.height = view.ly.height
        return ly.ly
    }
    
    func widthEqual(_ view: UIView) -> ExtensionHZLayoutable<UIView> {
        ly.frame.size.width = view.ly.width
        return ly.ly
    }
    
    func sizeEqual(_ view: UIView) -> ExtensionHZLayoutable<UIView> {
        ly.frame = CGRect(x: ly.frame.origin.x, y: ly.frame.origin.y, width: view.frame.size.width, height: view.frame.size.height)
        return ly.ly
    }
    
    func boundsEqual(_ view: UIView) -> ExtensionHZLayoutable<UIView> {
        ly.bounds = view.bounds
        return ly.ly
    }
    
    func frameEqual(_ view: UIView) -> ExtensionHZLayoutable<UIView> {
        ly.frame = view.frame
        return ly.ly
    }
    
    func leftEqual(_ view: UIView) -> ExtensionHZLayoutable<UIView> {
        ly.frame = CGRect(x: view.frame.origin.x, y: ly.frame.origin.y, width: ly.frame.size.width, height: ly.frame.size.height)
        return ly.ly
    }
    
    func rightEqual(_ view: UIView) -> ExtensionHZLayoutable<UIView> {
        
        var tmpFrame      = ly.frame
        tmpFrame.origin.x = view.ly.right - ly.frame.size.width
        ly.frame          = tmpFrame
        return ly.ly
    }
    
    func topEqual(_ view: UIView) -> ExtensionHZLayoutable<UIView> {
        
        var tmpFrame      = ly.frame
        tmpFrame.origin.y = view.ly.top
        ly.frame          = tmpFrame
        
        return ly.ly
    }
    
    func bottomEqual(_ view: UIView) -> ExtensionHZLayoutable<UIView> {
        
        var tmpFrame      = ly.frame
        tmpFrame.origin.y = view.ly.bottom - tmpFrame.height
        ly.frame          = tmpFrame
        
        return ly.ly
    }
    
    //SIZE fit
    func sizeToFit() -> ExtensionHZLayoutable<UIView> {
        
        ly.sizeToFit()
        return ly.ly
    }
    
    func sizeToFitEqual(width: CGFloat) -> ExtensionHZLayoutable<UIView> {
        
        let size = ly.sizeThatFits(CGSize(width: width, height: 0))
        var tmpFrame = ly.frame
        tmpFrame.size = size
        ly.frame = tmpFrame
        
        return ly.ly
    }
    
    func sizeToFitEqual(height: CGFloat) -> ExtensionHZLayoutable<UIView> {
        
        let size = ly.sizeThatFits(CGSize(width: 0, height: height))
        var tmpFrame = ly.frame
        tmpFrame.size = size
        ly.frame = tmpFrame
        return ly.ly
    }
    
    //width
    func set_width(width: CGFloat) -> ExtensionHZLayoutable<UIView> {
        
        var tmpFrame = ly.frame
        tmpFrame.size.width = width
        ly.frame = tmpFrame
        return ly.ly
    }
    
    func set_width(width: CGFloat, offset: CGFloat) -> ExtensionHZLayoutable<UIView> {
        
        var tmpFrame = ly.frame
        tmpFrame.size.width = width + offset
        ly.frame = tmpFrame
        return ly.ly
    }
    //height
    func set_height(height: CGFloat) -> ExtensionHZLayoutable<UIView> {
        
        var tmpFrame = ly.frame
        tmpFrame.size.height = height
        ly.frame = tmpFrame
        return ly.ly
    }
    
    func set_height(height: CGFloat, offset: CGFloat) -> ExtensionHZLayoutable<UIView> {
        
        var tmpFrame = ly.frame
        tmpFrame.size.height = height + offset
        ly.frame = tmpFrame
        return ly.ly
    }
    
    //left
    func set_left(left: CGFloat) -> ExtensionHZLayoutable<UIView> {
        
        var tmpFrame = ly.frame
        tmpFrame.origin.x = left
        ly.frame = tmpFrame
        return ly.ly
    }
    
    func set_left(left: CGFloat, offset: CGFloat) -> ExtensionHZLayoutable<UIView> {
        
        var tmpFrame = ly.frame
        tmpFrame.origin.x = left + offset
        ly.frame = tmpFrame
        return ly.ly
    }
    
    //right
    func set_right(right: CGFloat) -> ExtensionHZLayoutable<UIView> {
        
        var tmpFrame = ly.frame
        tmpFrame.origin.x = right - tmpFrame.width
        ly.frame = tmpFrame
        
        return ly.ly
    }
    
    func set_right(right: CGFloat, offset: CGFloat) -> ExtensionHZLayoutable<UIView> {
        
        var tmpFrame = ly.frame
        tmpFrame.origin.x = right - tmpFrame.width + offset
        ly.frame = tmpFrame
        return ly.ly
    }
    
    //top
    func set_top(top: CGFloat) -> ExtensionHZLayoutable<UIView> {
        
        var tmpFrame = ly.frame
        tmpFrame.origin.y = top
        ly.frame = tmpFrame
        return ly.ly
    }
    
    func set_top(top: CGFloat, offset: CGFloat) -> ExtensionHZLayoutable<UIView> {
        
        var tmpFrame = ly.frame
        tmpFrame.origin.y = top + offset
        ly.frame = tmpFrame
        return ly.ly
    }
    
    //bottom
    func set_bottom(bottom: CGFloat) -> ExtensionHZLayoutable<UIView> {
        
        var tmpFrame = ly.frame
        tmpFrame.origin.y = bottom - tmpFrame.height
        ly.frame = tmpFrame
        return ly.ly
    }
    
    func set_bottom(bottom: CGFloat, offset: CGFloat) -> ExtensionHZLayoutable<UIView> {
        
        var tmpFrame = ly.frame
        tmpFrame.origin.y = bottom - tmpFrame.height + offset
        ly.frame = tmpFrame
        return ly.ly
    }
    
    //center
    func set_center(center: CGPoint) -> ExtensionHZLayoutable<UIView> {

        ly.center = center
        return ly.ly
    }
    
    //centerX
    func set_centerX(centerX: CGFloat) -> ExtensionHZLayoutable<UIView> {
        
        ly.center = CGPoint(x: centerX, y: ly.center.y)
        return ly.ly
    }
    
    func set_centerX(centerX: CGFloat, offset: CGFloat) -> ExtensionHZLayoutable<UIView> {
        
        ly.center = CGPoint(x: centerX + offset, y: ly.center.y)
        return ly.ly
    }
    
    //centerY
    func set_centerY(centerY: CGFloat) -> ExtensionHZLayoutable<UIView> {
        
        ly.center = CGPoint(x: ly.center.x, y: centerY)
        return ly.ly
    }
    
    func set_centerY(centerY: CGFloat, offset: CGFloat) -> ExtensionHZLayoutable<UIView> {
        
        ly.center = CGPoint(x: ly.center.x, y: centerY + offset)
        return ly.ly
    }
    
    
    func set_size(size: CGSize) -> ExtensionHZLayoutable<UIView> {
        
        var tmpFrame = ly.frame
        tmpFrame.size = size
        ly.frame = tmpFrame
        
        return ly.ly
    }
    
    func underOf(view: UIView, offset: CGFloat) -> ExtensionHZLayoutable<UIView> {
        
        var tmpFrame = ly.frame
        tmpFrame.origin.y = view.ly.bottom + offset
        ly.frame = tmpFrame
        
        return ly.ly
    }
    
    func rightOf(view: UIView, offset: CGFloat) -> ExtensionHZLayoutable<UIView> {
        
        var tmpFrame = ly.frame
        tmpFrame.origin.x = view.ly.right + offset
        ly.frame = tmpFrame
        
        return ly.ly
    }
    
    func leftOf(view: UIView, offset: CGFloat) -> ExtensionHZLayoutable<UIView> {
        
        var tmpFrame = ly.frame
        tmpFrame.origin.x = view.ly.left + offset - tmpFrame.width
        ly.frame = tmpFrame
        
        return ly.ly
    }
    
    func aboveOf(view: UIView, offset: CGFloat) -> ExtensionHZLayoutable<UIView> {
        
        var tmpFrame = ly.frame
        tmpFrame.origin.y = view.ly.top + offset - tmpFrame.height
        ly.frame = tmpFrame
        
        return ly.ly
    }
    
    //MARK: getter and setter
    var viewOrigin : CGPoint {
        
        get { return ly.frame.origin}
        
        set(newVal) {
            
            var tmpFrame    = ly.frame
            tmpFrame.origin = newVal
            ly.frame        = tmpFrame
        }
    }
    
    /// viewSize
    var viewSize : CGSize {
        
        get{ return ly.frame.size}
        
        set(newVal) {
            
            var tmpFrame  = ly.frame
            tmpFrame.size = newVal
            ly.frame      = tmpFrame
        }
    }
    
    /// x
    var x : CGFloat {
        
        get { return ly.frame.origin.x}
        
        set(newVal) {
            
            var tmpFrame      = ly.frame
            tmpFrame.origin.x = newVal
            ly.frame          = tmpFrame
        }
    }
    
    /// y
    var y : CGFloat {
        
        get { return ly.frame.origin.y}
        
        set(newVal) {
            
            var tmpFrame      = ly.frame
            tmpFrame.origin.y = newVal
            ly.frame          = tmpFrame
        }
    }
    
    /// height
    var height : CGFloat {
        
        get { return ly.frame.size.height}
        
        set(newVal) {
            
            var tmpFrame         = ly.frame
            tmpFrame.size.height = newVal
            ly.frame             = tmpFrame
        }
    }
    
    /// width
    var width : CGFloat {
        
        get { return ly.frame.size.width}
        
        set(newVal) {
            
            var tmpFrame        = ly.frame
            tmpFrame.size.width = newVal
            ly.frame            = tmpFrame
        }
    }
    
    /// left
    var left : CGFloat {
        
        get { return ly.frame.origin.x}
        
        set(newVal) {
            
            var tmpFrame      = ly.frame
            tmpFrame.origin.x = newVal
            ly.frame          = tmpFrame
        }
    }
    
    /// right
    var right : CGFloat {
        
        get { return ly.frame.origin.x + ly.frame.size.width}
        
        set(newVal) {
            
            var tmpFrame      = ly.frame
            tmpFrame.origin.x = newVal - ly.frame.size.width
            ly.frame          = tmpFrame
        }
    }
    
    /// top
    var top : CGFloat {
        
        get { return ly.frame.origin.y}
        
        set(newVal) {
            
            var tmpFrame      = ly.frame
            tmpFrame.origin.y = newVal
            ly.frame          = tmpFrame
        }
    }
    
    /// bottom
    var bottom : CGFloat {
        
        get { return ly.frame.origin.y + ly.frame.size.height}
        
        set(newVal) {
            
            var tmpFrame      = ly.frame
            tmpFrame.origin.y = newVal - ly.frame.size.height
            ly.frame          = tmpFrame
        }
    }
    
    /// centerX
    var centerX : CGFloat {
        
        get { return ly.center.x}
        set(newVal) { ly.center = CGPoint(x: newVal, y: ly.center.y)}
    }
    
    /// centerY
    var centerY : CGFloat {
        
        get { return ly.center.y}
        set(newVal) { ly.center = CGPoint(x: ly.center.x, y: newVal)}
    }
    
    /// middleX
    var middleX : CGFloat {
        
        get { return ly.bounds.width / 2}
    }
    
    /// middleY
    var middleY : CGFloat {
        
        get { return ly.bounds.height / 2}
    }
    
    /// middlePoint
    var middlePoint : CGPoint {
        
        get { return CGPoint(x: ly.bounds.width / 2, y: ly.bounds.height / 2)}
    }

    
    
}

protocol HZLayoutable {
    
    associatedtype L
    
    var ly: L { get }
}

struct ExtensionHZLayoutable<T>: HZLayoutable {
    
    let ly: T
    
    init(ly: T) {
        
        self.ly = ly
    }
}

extension UIView {
    
    var ly: ExtensionHZLayoutable<UIView> {
        
        return ExtensionHZLayoutable(ly: self)
    }
}
